package com.test;

import java.awt.Color;
import java.awt.Desktop;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.IOException;
import java.util.Vector;

import javax.imageio.ImageIO;
import javax.swing.JPanel;

public class MyPanel extends JPanel implements KeyListener {

	private static final long serialVersionUID = 1L;
	// definit le hero
	public Hero hero = null;
	// definit un groupe de char ennemie
	public Vector<EnemyTank> ets = new Vector<EnemyTank>();
	// definit un groupe de bombe
	public Vector<Bombe> bb = new Vector<Bombe>();
	// definit le main Frame
	private MyTankGame jf = null;
	// definit un cv
	private CV cv = new CV();

	public boolean animated = true;

	public boolean compteur = true;

	int enSize = 5;
	int music = 0;
	int x = 0;
	int y = 0;
	int z;
	// les trois images construit une bombe.
	Image img1 = null;
	Image img2 = null;
	Image img3 = null;
	// le logo de cv
	Image img4 = null;
	// le logo de end
	Image img5 = null;
	AePlayWave apw = null;
	Thread t;

	public MyPanel(int flag) {

		hero = new Hero(300, 360);

		if (flag == 0) {
			// initialise les chars ennemis
			for (int i = 0; i < enSize; i++) {
				EnemyTank et = new EnemyTank((i + 1) * 100, 10);
				ets.add(et);
				t = new Thread(et);
				t.start();
			}
			apw = new AePlayWave("res/start.wav");
			apw.start();

		} else {
			Recorder rec = new Recorder();
			rec.getRecord();
			for (int i = 0; i < rec.getPts().size(); i++) {
				int x = rec.getPts().get(i).getX();
				int y = rec.getPts().get(i).getY();
				int direct = rec.getPts().get(i).getDirect();
				this.getEts().add(new EnemyTank(x, y, direct));
			}

			// pour continuer une partie enregistr��e
			for (int i = 0; i < ets.size(); i++) {
				EnemyTank et = ets.get(i);
				t = new Thread(et);
				t.start();
			}

		}
		// on donne les informations a tous les chars ennemis
		Vector<Tank> tank = new Vector<Tank>();
		tank.addAll(ets);
		for (int i = 0; i < ets.size(); i++) {
			ets.get(i).setHero(hero);
			ets.get(i).setEts(tank);

		}

		// initialiser le cv
		cv.setMp(this);
		// t = new Thread(cv);
		// t.start();

		// initialiser les images
		try {
			img1 = ImageIO.read(this.getClass().getResourceAsStream("bomb_1.gif"));
			img2 = ImageIO.read(this.getClass().getResourceAsStream("bomb_2.gif"));
			img3 = ImageIO.read(this.getClass().getResourceAsStream("bomb_3.gif"));
			img4 = ImageIO.read(this.getClass().getResourceAsStream("resume.png"));
			img5 = ImageIO.read(this.getClass().getResourceAsStream("end.png"));

		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}

		// AePlayWave apw=new
		// AePlayWave(getClass().getResource("111.wav").toString());

	}

	public void paint(Graphics g) {
		super.paint(g);
		g.fillRect(0, 0, 600, 400);

		// on dessine mon char hero

		if (hero.isAlive()) {
			this.drawTank(hero.getX(), hero.getY(), g, hero.getDirect(),
					hero.getColor());
		}

		// on dessine le char ennemie
		for (int i = 0; i < ets.size(); i++) {
			if (ets.get(i).isAlive()) {
				this.drawTank(ets.get(i).getX(), ets.get(i).getY(), g,
						ets.get(i).getDirect(), ets.get(i).color);
			} else {
				ets.remove(i);
			}

		}

		// ---------------------------------------------------------------------
		// on dessine autant de munition lancee par hero
		for (int i = 0; i < hero.mm.size(); i++) {
			Munition mamunition = hero.mm.get(i);

			if (mamunition != null && mamunition.isAlive() == true) {
				g.setColor(Color.white);
				g.fill3DRect(mamunition.getX(), mamunition.getY(), 3, 3, false);

				// verifie chaque munition si elle touche un des chars existants
				for (int j = 0; j < ets.size(); j++) {
					toucheChar(mamunition, ets.get(j));
					// si ce char est mort, on l'enleve

					if (ets.get(j).isAlive() == false) {
						ets.remove(j);
					}
				}

			}
			// on enleve la munition quand elle est morte
			if (mamunition.isAlive() == false) {
				hero.mm.remove(mamunition);
			}
		}

		// -------------------------------------------------------------------------------
		// on dessine autant de munition lancee par char ennemis

		// tous les chars ennemis
		for (int i = 0; i < ets.size(); i++) {
			EnemyTank et = ets.get(i);

			// tous les munitions lancees par ce char
			for (int k = 0; k < et.getMm().size(); k++) {
				Munition mamunition = et.getMm().get(k);
				if (mamunition != null && mamunition.isAlive() == true) {
					g.setColor(Color.white);
					g.fill3DRect(mamunition.getX(), mamunition.getY(), 3, 3,
							false);

					// verifie chaque munition si elle touche un des chars
					// existants

					toucheHero(mamunition, this.hero);

				}
				if (mamunition.isAlive() == false) {
					et.getMm().remove(mamunition);

				}
			}// on enleve la munition quand elle est morte

		}

		// -----------------------------------------------------------------------------------
		// on dessine les bombes
		for (int i = 0; i < bb.size(); i++) {
			Bombe b = bb.get(i);

			if (b.getLife() > 300) {
				g.drawImage(img1, b.getX(), b.getY(), 25, 25, this);
			} else if (b.getLife() > 100) {
				g.drawImage(img2, b.getX(), b.getY(), 25, 25, this);
			} else {
				g.drawImage(img3, b.getX(), b.getY(), 25, 25, this);
			}

			// on diminue la vie d'une bombe
			b.lifedown();
			// si la bome est morte,on l'enleve
			if (b.getLife() == 0) {
				bb.remove(b);

			}
		}

		// -------------------------------------------------------------------------------------
		// afficher le logo de cv
		if (ets.size() == 0) {
			if (compteur) {
				t = new Thread(cv);
				t.start();
				compteur = false;
			}
			// On dessine le cv aux coordonn��es souhait��es
			g.drawImage(img4, cv.getPosX(), cv.getPosY(), 50, 50, this);
			if (animated) {
				// si le hero touche le logo,on ouvre le cv
				toucheCV(cv, hero);
			} else {

				// this.getJf().setExtendedState(JFrame.NORMAL);
				// this.getJf().toFront();

				// on affiche toujours le logo end au milieu de l'ecran,et on le
				// grandit
				g.drawImage(img5, this.getWidth() / 2 - x / 2, this.getHeight()
						/ 2 - y / 2 +3, x, y, this);
				try {
					Thread.sleep(20);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

				if (x < this.getWidth() + 15) {
					x += 2;
				}
				if (y < this.getHeight() + 20) {
					y += 1;
					z = y;
				} else {

					if (z == this.getHeight() + 230) {
						System.exit(0);
					}
					try {
						Thread.sleep(20);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					z += 1;
				}
			}

		}

		// repaint
		this.repaint();

	}

	public Vector<EnemyTank> getEts() {
		return ets;
	}

	public void setEts(Vector<EnemyTank> ets) {
		this.ets = ets;
	}

	public MyTankGame getJf() {
		return jf;
	}

	public void setJf(MyTankGame jf) {
		this.jf = jf;
	}

	// -----------------------------------------------------------------------------------
	// une fonction pour verifier si le hero touche le cv
	public void toucheCV(CV m, Hero h) {
		if (Math.abs(m.getPosX() + 25 - h.getX()) < 35
				&& Math.abs(m.getPosY() + 25 - h.getY()) < 35) {
			apw = new AePlayWave("res/end.wav");
			apw.start();

			Desktop desk = Desktop.getDesktop();
			File file = new File("res/cv.pdf");
			try {
				desk.open(file);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			this.animated = false;
//			try {
//				InputStream is = this.getClass().getResourceAsStream("cv.pdf");
//				//System.getProperty("java.io.tmp");
//				File file = new File("cv.pdf");
//				FileOutputStream os = new FileOutputStream(file);
//				
//				 byte[] buffer = new byte[1024];
//		         int bytesRead;
//		            //read from is to buffer
//		            while((bytesRead = is.read(buffer)) !=-1){
//		                os.write(buffer, 0, bytesRead);
//		            }
//		            is.close();
//		            //flush OutputStream to write any buffered data to file
//		            os.flush();
//		            os.close();
//				
//				desk.open(file);
//				
//				this.animated = false;
//
//			} catch (Exception e) {
//				System.out.println(e.toString());
//			}
		}
	}

	// -----------------------------------------------------------------------------------
	// une fonction pour verifier si une munition touche un char
	public void toucheChar(Munition m, EnemyTank et) {
		if (m.getX() + 3 > et.getX() - 10 && m.getX() < et.getX() + 10
				&& m.getY() < et.getY() + 10 && m.getY() + 3 > et.getY() - 10) {
			// la munition est morte et ce char est mort aussi
			m.setAlive(false);
			et.setAlive(false);

			// on construit une bombe
			Bombe b = new Bombe(et.getX() - 10, et.getY() - 10);
			// on ajoute cette bombe dans Vector bb
			bb.add(b);
		}
	}

	// une fonction pour verifier si une munition touche notre hero
	@SuppressWarnings("deprecation")
	public void toucheHero(Munition m, Hero h) {
		if (m.getX() + 3 > h.getX() - 10 && m.getX() < h.getX() + 10
				&& m.getY() < h.getY() + 10 && m.getY() + 3 > h.getY() - 10) {
			// la munition est morte
			m.setAlive(false);
			// Notre hero est en mode Dieu!!!
			if (music == 0) {
				apw = new AePlayWave("res/god.wav");
				apw.start();
				music += 1;

				// Vibre la JFrame
				int x, y, i;
				for (i = 0; i < 1000; i++) {
					x = (int) (Math.random() * 15 + 300);
					y = (int) (Math.random() * 15 + 150);
					this.getJf().setLocation(x, y);
					// on redessine le Panel en m��me temps
					this.repaint();
				}

			} else if (music == 2) {
				apw.stop();
				apw = new AePlayWave("res/god2.wav");
				apw.start();
				music += 1;

				for (int i = 0; i < ets.size(); i++) {
					ets.get(i).setAlive(false);
					// on explose tous les chars
					Bombe b = new Bombe(ets.get(i).getX() - 10, ets.get(i)
							.getY() - 10);
					// on ajoute cette bombe dans Vector bb
					bb.add(b);
					// ets.remove(i);

				}
			} else {
				music += 1;
			}
		}
	}

	// ------------------------------
	// draw Tank(extension)
	public void drawTank(int x, int y, Graphics g, int direct, int type) {
		// type
		switch (type) {
		case 0:
			g.setColor(Color.cyan);
			// direction

			switch (direct) {
			// haut
			case 0:
				g.fill3DRect(x - 5, y - 5, 10, 10, false);

				g.fill3DRect(x - 10, y - 10, 5, 20, false);

				g.fill3DRect(x + 5, y - 10, 5, 20, false);

				g.setColor(Color.red);

				g.fillOval(x - 5, y - 5, 10, 10);

				g.fillRect(x - 1, y - 10, 3, 10);

				break;
			// bas
			case 1:
				g.fill3DRect(x - 5, y - 5, 10, 10, false);

				g.fill3DRect(x - 10, y - 10, 5, 20, false);

				g.fill3DRect(x + 5, y - 10, 5, 20, false);

				g.setColor(Color.red);

				g.fillOval(x - 5, y - 5, 10, 10);

				g.fillRect(x - 1, y, 3, 10);
				break;
			// gauche
			case 2:
				g.fill3DRect(x - 5, y - 5, 10, 10, false);

				g.fill3DRect(x - 10, y - 10, 20, 5, false);

				g.fill3DRect(x - 10, y + 5, 20, 5, false);

				g.setColor(Color.red);

				g.fillOval(x - 5, y - 5, 10, 10);

				g.fillRect(x - 10, y - 1, 10, 3);
				break;
			// droite
			case 3:
				g.fill3DRect(x - 5, y - 5, 10, 10, false);

				g.fill3DRect(x - 10, y - 10, 20, 5, false);

				g.fill3DRect(x - 10, y + 5, 20, 5, false);

				g.setColor(Color.red);

				g.fillOval(x - 5, y - 5, 10, 10);

				g.fillRect(x, y - 1, 10, 3);
				break;
			}
			break;
		case 1:

			// direction

			switch (direct) {
			// haut
			case 0:
				g.setColor(Color.white);
				g.fill3DRect(x - 5, y - 5, 10, 10, false);
				g.setColor(Color.blue);
				g.fill3DRect(x - 10, y - 10, 5, 20, false);
				g.setColor(Color.red);
				g.fill3DRect(x + 5, y - 10, 5, 20, false);

				g.setColor(Color.white);
				g.fillOval(x - 5, y - 5, 10, 10);

				g.fillRect(x - 1, y - 10, 3, 10);

				break;
			// bas
			case 1:
				g.setColor(Color.white);
				g.fill3DRect(x - 5, y - 5, 10, 10, false);
				g.setColor(Color.red);
				g.fill3DRect(x - 10, y - 10, 5, 20, false);
				g.setColor(Color.blue);
				g.fill3DRect(x + 5, y - 10, 5, 20, false);

				g.setColor(Color.white);
				g.fillOval(x - 5, y - 5, 10, 10);

				g.fillRect(x - 1, y, 3, 10);
				break;
			// gauche
			case 2:
				g.setColor(Color.white);
				g.fill3DRect(x - 5, y - 5, 10, 10, false);
				g.setColor(Color.red);
				g.fill3DRect(x - 10, y - 10, 20, 5, false);
				g.setColor(Color.blue);
				g.fill3DRect(x - 10, y + 5, 20, 5, false);

				g.setColor(Color.white);
				g.fillOval(x - 5, y - 5, 10, 10);

				g.fillRect(x - 10, y - 1, 10, 3);
				break;
			// droite
			case 3:
				g.setColor(Color.white);
				g.fill3DRect(x - 5, y - 5, 10, 10, false);
				g.setColor(Color.blue);
				g.fill3DRect(x - 10, y - 10, 20, 5, false);
				g.setColor(Color.red);
				g.fill3DRect(x - 10, y + 5, 20, 5, false);

				g.setColor(Color.white);
				g.fillOval(x - 5, y - 5, 10, 10);

				g.fillRect(x, y - 1, 10, 3);
				break;
			}
			break;
		}

	}

	public boolean bloquer(Hero h, Vector<EnemyTank> ets, int direct) {
		boolean res = true;
		switch (direct) {
		case 0:
			for (int i = 0; i < ets.size(); i++) {
				EnemyTank et = ets.get(i);
				if (Math.abs(h.getX() - et.getX()) < 20
						&& Math.abs(h.getY() - h.getSpeed() - et.getY()) < 20) {
					res = false;
					h.setY(et.getY() + 20);// on touche le bord sud du char
											// ennemi

				}
			}
			break;
		case 1:
			for (int i = 0; i < ets.size(); i++) {
				EnemyTank et = ets.get(i);
				if (Math.abs(h.getX() - et.getX()) < 20
						&& Math.abs(h.getY() + h.getSpeed() - et.getY()) < 20) {
					res = false;
					h.setY(et.getY() - 20);// on touche le bord nord du char
											// ennemi
				}
			}
			break;
		case 2:
			for (int i = 0; i < ets.size(); i++) {
				EnemyTank et = ets.get(i);
				if (Math.abs(h.getX() - h.getSpeed() - et.getX()) < 20
						&& Math.abs(h.getY() - et.getY()) < 20)

				{
					res = false;
					h.setX(et.getX() + 20);// on touche le bord est du char
											// ennemi
				}
			}
			break;
		case 3:
			for (int i = 0; i < ets.size(); i++) {
				EnemyTank et = ets.get(i);
				if (Math.abs(h.getX() + h.getSpeed() - et.getX()) < 20
						&& Math.abs(h.getY() - et.getY()) < 20) {
					res = false;
					h.setX(et.getX() - 20);// on touche le bord ouest du char
											// ennemi
				}
			}
			break;
		}

		return res;
	}

	@Override
	public void keyPressed(KeyEvent arg0) {
		// TODO Auto-generated method stub

		if (animated) {
			if (arg0.getKeyCode() == KeyEvent.VK_Z
					|| arg0.getKeyCode() == KeyEvent.VK_UP) {

				if (bloquer(this.hero, ets, 0)) {// definit la direction de mon
													// char
					this.hero.setDirect(0);

					if (this.hero.getY() - 10 > 0) {
						this.hero.moveUp();
					} else {
						this.hero.setY(10);
					}
				}

			} else if (arg0.getKeyCode() == KeyEvent.VK_S
					|| arg0.getKeyCode() == KeyEvent.VK_DOWN) {

				if (bloquer(this.hero, ets, 1)) {
					this.hero.setDirect(1);
					if (this.hero.getY() + 15 < this.getHeight()) {
						this.hero.moveDown();
					} else {
						this.hero.setY(this.getHeight() - 10);
					}
				}

			} else if (arg0.getKeyCode() == KeyEvent.VK_Q
					|| arg0.getKeyCode() == KeyEvent.VK_LEFT) {
				if (bloquer(this.hero, ets, 2)) {

					this.hero.setDirect(2);
					if (this.hero.getX() - 10 > 0) {
						this.hero.moveLeft();
					} else {
						this.hero.setX(10);
					}
				}
			} else if (arg0.getKeyCode() == KeyEvent.VK_D
					|| arg0.getKeyCode() == KeyEvent.VK_RIGHT) {
				if (bloquer(this.hero, ets, 3)) {
					this.hero.setDirect(3);
					if (this.hero.getX() + 10 < this.getWidth()) {
						this.hero.moveRight();
					} else {
						this.hero.setX(this.getWidth() - 10);
					}
				}

			}

			if (arg0.getKeyCode() == KeyEvent.VK_SPACE) {

				// Hero peut tirer 5 munitions en meme temps
				if (hero.mm.size() < 5) {
					this.hero.tirer();

				}
			}
			// on redessine le Panel
			this.repaint();
		}
	}

	@Override
	public void keyReleased(KeyEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void keyTyped(KeyEvent arg0) {
		// TODO Auto-generated method stub

	}

	public void clear() {
		// TODO Auto-generated method stub
		for (int i = 0; i < ets.size(); i++) {
			ets.get(i).setAlive(false);
		}
		hero.setAlive(false);

	}

}
